package org.jeecg.access.platform.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * JSON解析工具类
 * 提供JSON节点值获取（支持String/Integer/Long/Boolean等封装类型）、接口返回状态判断、条件查询、列表长度获取等功能
 * 支持处理嵌套节点和数组结构，内置缓存机制减少重复解析开销
 * 所有数值类型返回封装类，null表示获取失败或节点不存在
 *
 * @author taogang
 * @date 2025/8/6 11:56
 */
@Slf4j
public class JsonParserUtils {

    /** JSON序列化/反序列化核心工具 */
    private static final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 缓存JSON字符串解析结果
     * 键：JSON字符串内容，值：解析后的JsonNode及创建时间（用于过期判断）
     */
    private static final Map<String, CacheEntry> jsonStringCache = new HashMap<>();

    /**
     * 缓存JSON文件解析结果
     * 键：文件绝对路径，值：解析后的JsonNode、文件最后修改时间及创建时间（用于过期判断）
     */
    private static final Map<String, FileCacheEntry> jsonFileCache = new HashMap<>();

    /** 缓存过期时间（30秒） */
    private static final long CACHE_EXPIRE_SECONDS = 30;

    /** 缓存读写锁（保证并发安全，读多写少场景优化） */
    private static final ReentrantReadWriteLock cacheLock = new ReentrantReadWriteLock();


    /**
     * 缓存条目类（用于JSON字符串缓存）
     */
    private static class CacheEntry {
        /** 解析后的JSON节点 */
        JsonNode node;
        /** 缓存创建时间（毫秒时间戳） */
        long createTime;

        CacheEntry(JsonNode node) {
            this.node = node;
            this.createTime = System.currentTimeMillis();
        }

        /**
         * 判断缓存是否过期
         * @return true-已过期，false-未过期
         */
        boolean isExpired() {
            return System.currentTimeMillis() - createTime > CACHE_EXPIRE_SECONDS * 1000;
        }
    }

    /**
     * 缓存条目类（用于JSON文件缓存，继承自字符串缓存条目）
     */
    private static class FileCacheEntry extends CacheEntry {
        /** 文件最后修改时间（毫秒时间戳，用于判断文件是否更新） */
        long fileLastModified;

        FileCacheEntry(JsonNode node, long fileLastModified) {
            super(node);
            this.fileLastModified = fileLastModified;
        }
    }


    // ========================== 接口返回状态判断 ==========================

    /**
     * 判断接口返回是否成功（默认基于"code"字段判断，成功值为"200"）
     * 规则：存在"code"字段且值为"200"（数字或字符串形式均可）视为成功
     *
     * @param jsonStr JSON格式的响应字符串
     * @return Boolean-成功返回true，失败返回false；解析异常返回null
     */
    public static Boolean isSuccess(String jsonStr) {
        return isSuccess(jsonStr, "code", "200");
    }

    /**
     * 通用方法：判断接口返回是否成功（自定义状态字段和成功值）
     *
     * @param jsonStr      JSON格式的响应字符串
     * @param statusField  状态字段名（如"code"、"status"、"success"）
     * @param successValue 成功状态值（如"200"、"0"、"true"）
     * @return Boolean-成功返回true，失败返回false；解析异常/参数无效返回null
     */
    public static Boolean isSuccess(String jsonStr, String statusField, String successValue) {
        // 入参校验
        if (jsonStr == null || jsonStr.trim().isEmpty()) {
            log.error("判断返回状态失败：JSON字符串为空");
            return null;
        }
        if (statusField == null || statusField.trim().isEmpty()) {
            log.error("判断返回状态失败：状态字段名为空");
            return null;
        }
        if (successValue == null) {
            log.error("判断返回状态失败：成功状态值为空");
            return null;
        }

        try {
            // 从缓存获取或解析JSON节点
            JsonNode rootNode = getJsonNodeFromString(jsonStr);
            if (rootNode == null) {
                return null; // 解析失败
            }

            // 获取状态字段节点
            JsonNode statusNode = rootNode.get(statusField);
            if (statusNode == null) {
                log.warn("判断返回状态警告：JSON中不存在字段[{}]", statusField);
                return false;
            }

            // 比较状态值（转为字符串后比较，兼容数字/字符串类型）
            return successValue.equals(statusNode.asText());
        } catch (Exception e) {
            log.error("判断返回状态异常：JSON字符串=[{}]，错误信息=[{}]", jsonStr, e.getMessage(), e);
            return null;
        }
    }


    // ========================== 从JSON字符串获取节点值（多类型） ==========================

    /**
     * 从JSON字符串获取节点的字符串值（带缓存）
     *
     * @param jsonStr  JSON格式字符串
     * @param nodePath 节点路径（支持嵌套，如"user.name"；支持数组，如"list[0].id"）
     * @return String-节点的字符串值；节点不存在或解析失败时返回null
     */
    public static String getStringValueFromString(String jsonStr, String nodePath) {
        JsonNode targetNode = getTargetNodeFromString(jsonStr, nodePath);
        return targetNode != null ? targetNode.asText() : null;
    }

    /**
     * 从JSON字符串获取节点的Integer值（带缓存）
     *
     * @param jsonStr  JSON格式字符串
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Integer-节点的整数 value；节点不存在/解析失败/类型转换失败时返回null
     */
    public static Integer getIntValueFromString(String jsonStr, String nodePath) {
        JsonNode targetNode = getTargetNodeFromString(jsonStr, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            // 若节点为字符串类型，尝试手动转换（避免asInt()默认返回0）
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim();
                if (textValue.isEmpty()) {
                    return null;
                }
                return Integer.parseInt(textValue);
            }
            return targetNode.asInt();
        } catch (NumberFormatException e) {
            log.error("JSON节点[{}]转换为Integer失败：{}", nodePath, e.getMessage());
            return null;
        }
    }

    /**
     * 从JSON字符串获取节点的Long值（带缓存）
     *
     * @param jsonStr  JSON格式字符串
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Long-节点的长整数 value；节点不存在/解析失败/类型转换失败时返回null
     */
    public static Long getLongValueFromString(String jsonStr, String nodePath) {
        JsonNode targetNode = getTargetNodeFromString(jsonStr, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            // 若节点为字符串类型，尝试手动转换（避免asLong()默认返回0）
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim();
                if (textValue.isEmpty()) {
                    return null;
                }
                return Long.parseLong(textValue);
            }
            return targetNode.asLong();
        } catch (NumberFormatException e) {
            log.error("JSON节点[{}]转换为Long失败：{}", nodePath, e.getMessage());
            return null;
        }
    }

    /**
     * 从JSON字符串获取节点的Boolean值（带缓存）
     *
     * @param jsonStr  JSON格式字符串
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Boolean-节点的布尔值；节点不存在/解析失败时返回null；节点值为"true"/true返回true，否则返回false
     */
    public static Boolean getBooleanValueFromString(String jsonStr, String nodePath) {
        JsonNode targetNode = getTargetNodeFromString(jsonStr, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            // 处理字符串类型的布尔值（如"true"）
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim().toLowerCase();
                return "true".equals(textValue);
            }
            return targetNode.asBoolean();
        } catch (Exception e) {
            log.error("JSON节点[{}]转换为Boolean失败：{}", nodePath, e.getMessage());
            return null;
        }
    }


    // ========================== 从JSON文件获取节点值（多类型） ==========================

    /**
     * 从JSON文件获取节点的字符串值（带缓存，基于文件修改时间更新）
     *
     * @param jsonFile JSON文件对象
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return String-节点的字符串值；文件不存在/节点不存在/解析失败时返回null
     */
    public static String getStringValueFromFile(File jsonFile, String nodePath) {
        JsonNode targetNode = getTargetNodeFromFile(jsonFile, nodePath);
        return targetNode != null ? targetNode.asText() : null;
    }

    /**
     * 从JSON文件获取节点的Integer值（带缓存）
     *
     * @param jsonFile JSON文件对象
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Integer-节点的整数 value；文件不存在/节点不存在/解析失败/转换失败时返回null
     */
    public static Integer getIntValueFromFile(File jsonFile, String nodePath) {
        JsonNode targetNode = getTargetNodeFromFile(jsonFile, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim();
                if (textValue.isEmpty()) {
                    return null;
                }
                return Integer.parseInt(textValue);
            }
            return targetNode.asInt();
        } catch (NumberFormatException e) {
            log.error("JSON文件节点[{}]转换为Integer失败：{}", nodePath, e.getMessage());
            return null;
        }
    }

    /**
     * 从JSON文件获取节点的Long值（带缓存）
     *
     * @param jsonFile JSON文件对象
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Long-节点的长整数 value；文件不存在/节点不存在/解析失败/转换失败时返回null
     */
    public static Long getLongValueFromFile(File jsonFile, String nodePath) {
        JsonNode targetNode = getTargetNodeFromFile(jsonFile, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim();
                if (textValue.isEmpty()) {
                    return null;
                }
                return Long.parseLong(textValue);
            }
            return targetNode.asLong();
        } catch (NumberFormatException e) {
            log.error("JSON文件节点[{}]转换为Long失败：{}", nodePath, e.getMessage());
            return null;
        }
    }

    /**
     * 从JSON文件获取节点的Boolean值（带缓存）
     *
     * @param jsonFile JSON文件对象
     * @param nodePath 节点路径（支持嵌套和数组）
     * @return Boolean-节点的布尔值；文件不存在/节点不存在/解析失败时返回null；节点值为"true"/true返回true，否则返回false
     */
    public static Boolean getBooleanValueFromFile(File jsonFile, String nodePath) {
        JsonNode targetNode = getTargetNodeFromFile(jsonFile, nodePath);
        if (targetNode == null) {
            return null;
        }
        try {
            if (targetNode.isTextual()) {
                String textValue = targetNode.asText().trim().toLowerCase();
                return "true".equals(textValue);
            }
            return targetNode.asBoolean();
        } catch (Exception e) {
            log.error("JSON文件节点[{}]转换为Boolean失败：{}", nodePath, e.getMessage());
            return null;
        }
    }


    // ========================== 条件查询（多类型） ==========================

    /**
     * 从JSON数组中根据条件匹配，获取目标字段的字符串值
     *
     * @param jsonStr        JSON格式字符串
     * @param arrayPath      数组节点路径（如"users"、"data.list"）
     * @param conditionField 条件字段名（如"id"）
     * @param conditionValue 条件字段值（如"123"）
     * @param targetField    目标字段名（如"name"）
     * @return String-目标字段值；未找到/解析失败返回null
     */
    public static String getStringValueByCondition(String jsonStr, String arrayPath,
                                                   String conditionField, String conditionValue,
                                                   String targetField) {
        // 入参校验
        if (jsonStr == null || jsonStr.trim().isEmpty() || arrayPath == null || arrayPath.trim().isEmpty()
                || conditionField == null || conditionField.trim().isEmpty() || conditionValue == null
                || targetField == null || targetField.trim().isEmpty()) {
            log.error("条件查询参数无效，存在空值");
            return null;
        }

        try {
            // 获取数组节点
            JsonNode arrayNode = getTargetNodeFromString(jsonStr, arrayPath);
            if (arrayNode == null || !arrayNode.isArray()) {
                log.error("数组路径[{}]无效或不是数组", arrayPath);
                return null;
            }

            // 遍历数组查找匹配对象（传统for循环）
            JsonNode targetNode = findTargetNodeInArray(arrayNode, conditionField, conditionValue, targetField);
            return targetNode != null ? targetNode.asText() : null;
        } catch (Exception e) {
            log.error("字符串条件查询异常", e);
            return null;
        }
    }

    /**
     * 从JSON数组中根据条件匹配，获取目标字段的Integer值
     *
     * @param jsonStr        JSON格式字符串
     * @param arrayPath      数组节点路径
     * @param conditionField 条件字段名
     * @param conditionValue 条件字段值
     * @param targetField    目标字段名
     * @return Integer-目标字段值；未找到/解析失败/类型不匹配返回null
     */
    public static Integer getIntValueByCondition(String jsonStr, String arrayPath,
                                                 String conditionField, String conditionValue,
                                                 String targetField) {
        try {
            JsonNode targetNode = getTargetNodeByCondition(jsonStr, arrayPath, conditionField, conditionValue, targetField);
            if (targetNode == null) {
                return null;
            }

            // 处理字符串类型的整数（如"123"）
            if (targetNode.isTextual()) {
                String text = targetNode.asText().trim();
                return text.isEmpty() ? null : Integer.parseInt(text);
            }
            return targetNode.isNumber() ? targetNode.asInt() : null;
        } catch (NumberFormatException e) {
            log.error("目标字段[{}]转换为Integer失败", targetField, e);
            return null;
        } catch (Exception e) {
            log.error("整数条件查询异常", e);
            return null;
        }
    }

    /**
     * 从JSON数组中根据条件匹配，获取目标字段的Long值
     *
     * @param jsonStr        JSON格式字符串
     * @param arrayPath      数组节点路径
     * @param conditionField 条件字段名
     * @param conditionValue 条件字段值
     * @param targetField    目标字段名
     * @return Long-目标字段值；未找到/解析失败/类型不匹配返回null
     */
    public static Long getLongValueByCondition(String jsonStr, String arrayPath,
                                               String conditionField, String conditionValue,
                                               String targetField) {
        try {
            JsonNode targetNode = getTargetNodeByCondition(jsonStr, arrayPath, conditionField, conditionValue, targetField);
            if (targetNode == null) {
                return null;
            }

            // 处理字符串类型的长整数（如"123456789"）
            if (targetNode.isTextual()) {
                String text = targetNode.asText().trim();
                return text.isEmpty() ? null : Long.parseLong(text);
            }
            return targetNode.isNumber() ? targetNode.asLong() : null;
        } catch (NumberFormatException e) {
            log.error("目标字段[{}]转换为Long失败", targetField, e);
            return null;
        } catch (Exception e) {
            log.error("长整数条件查询异常", e);
            return null;
        }
    }

    /**
     * 从JSON数组中根据条件匹配，获取目标字段的Boolean值
     *
     * @param jsonStr        JSON格式字符串
     * @param arrayPath      数组节点路径
     * @param conditionField 条件字段名
     * @param conditionValue 条件字段值
     * @param targetField    目标字段名
     * @return Boolean-目标字段值；未找到/解析失败返回null
     */
    public static Boolean getBooleanValueByCondition(String jsonStr, String arrayPath,
                                                     String conditionField, String conditionValue,
                                                     String targetField) {
        try {
            JsonNode targetNode = getTargetNodeByCondition(jsonStr, arrayPath, conditionField, conditionValue, targetField);
            if (targetNode == null) {
                return null;
            }

            // 处理字符串类型的布尔值（如"true"、"false"）
            if (targetNode.isTextual()) {
                String text = targetNode.asText().trim().toLowerCase();
                return "true".equals(text) ? Boolean.TRUE : "false".equals(text) ? Boolean.FALSE : null;
            }
            return targetNode.isBoolean() ? targetNode.asBoolean() : null;
        } catch (Exception e) {
            log.error("布尔值条件查询异常", e);
            return null;
        }
    }


    // ========================== 获取JSON数组长度 ==========================

    /**
     * 获取JSON字符串中指定数组节点的长度
     *
     * @param jsonStr  JSON格式字符串
     * @param listPath 数组节点路径（如"users"、"data.list[0].items"）
     * @return Integer-数组长度；节点不存在/不是数组/解析失败/参数无效时返回null
     */
    public static Integer getListLength(String jsonStr, String listPath) {
        // 入参校验
        if (jsonStr == null || jsonStr.trim().isEmpty()) {
            log.error("获取列表长度失败：JSON字符串为空");
            return null;
        }
        if (listPath == null || listPath.trim().isEmpty()) {
            log.error("获取列表长度失败：列表路径为空");
            return null;
        }

        try {
            // 获取数组节点
            JsonNode listNode = getTargetNodeFromString(jsonStr, listPath);
            if (listNode == null) {
                log.error("获取列表长度失败：未找到路径[{}]的节点", listPath);
                return null;
            }
            if (!listNode.isArray()) {
                log.error("获取列表长度失败：路径[{}]的节点不是数组", listPath);
                return null;
            }
            return listNode.size();
        } catch (Exception e) {
            log.error("获取列表长度异常：JSON字符串=[{}]，错误信息=[{}]", jsonStr, e.getMessage(), e);
            return null;
        }
    }


    // ========================== 私有辅助方法 ==========================

    /**
     * 从JSON字符串中获取目标节点（带缓存处理）
     *
     * @param jsonStr  JSON格式字符串
     * @param nodePath 节点路径
     * @return 目标节点；解析失败或节点不存在时返回null
     */
    private static JsonNode getTargetNodeFromString(String jsonStr, String nodePath) {
        // 入参校验
        if (jsonStr == null || jsonStr.trim().isEmpty()) {
            log.error("获取目标节点失败：JSON字符串为空");
            return null;
        }
        if (nodePath == null || nodePath.trim().isEmpty()) {
            log.error("获取目标节点失败：节点路径为空");
            return null;
        }

        // 获取根节点
        JsonNode rootNode = getJsonNodeFromString(jsonStr);
        if (rootNode == null) {
            return null;
        }

        // 从根节点导航到目标节点
        return getNodeFromPath(rootNode, nodePath);
    }

    /**
     * 从JSON文件中获取目标节点（带缓存处理）
     *
     * @param jsonFile JSON文件对象
     * @param nodePath 节点路径
     * @return 目标节点；文件不存在/解析失败/节点不存在时返回null
     */
    private static JsonNode getTargetNodeFromFile(File jsonFile, String nodePath) {
        // 入参校验
        if (jsonFile == null) {
            log.error("获取目标节点失败：JSON文件对象为空");
            return null;
        }
        if (!jsonFile.exists()) {
            log.error("获取目标节点失败：文件不存在，路径=[{}]", jsonFile.getAbsolutePath());
            return null;
        }
        if (!jsonFile.isFile()) {
            log.error("获取目标节点失败：不是有效文件，路径=[{}]", jsonFile.getAbsolutePath());
            return null;
        }
        if (nodePath == null || nodePath.trim().isEmpty()) {
            log.error("获取目标节点失败：节点路径为空");
            return null;
        }

        // 获取根节点
        JsonNode rootNode = getJsonNodeFromFile(jsonFile);
        if (rootNode == null) {
            return null;
        }

        // 从根节点导航到目标节点
        return getNodeFromPath(rootNode, nodePath);
    }

    /**
     * 从JSON字符串获取根节点（带缓存）
     *
     * @param jsonStr JSON格式字符串
     * @return 解析后的根节点；解析失败时返回null
     */
    private static JsonNode getJsonNodeFromString(String jsonStr) {
        try {
            // 尝试从缓存读取（读锁）
            cacheLock.readLock().lock();
            CacheEntry entry = jsonStringCache.get(jsonStr);
            cacheLock.readLock().unlock();

            // 缓存命中且未过期
            if (entry != null && !entry.isExpired()) {
                return entry.node;
            }

            // 缓存未命中或过期，重新解析
            JsonNode rootNode = objectMapper.readTree(jsonStr);

            // 更新缓存（写锁）
            cacheLock.writeLock().lock();
            jsonStringCache.put(jsonStr, new CacheEntry(rootNode));
            cacheLock.writeLock().unlock();

            return rootNode;
        } catch (JsonProcessingException e) {
            log.error("JSON字符串解析失败：{}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从JSON文件获取根节点（带缓存，基于文件修改时间）
     *
     * @param jsonFile JSON文件对象
     * @return 解析后的根节点；文件不存在/解析失败时返回null
     */
    private static JsonNode getJsonNodeFromFile(File jsonFile) {
        String filePath = jsonFile.getAbsolutePath();
        try {
            // 获取文件最后修改时间
            long fileLastModified = Files.readAttributes(
                    Paths.get(filePath), BasicFileAttributes.class
            ).lastModifiedTime().toMillis();

            // 尝试从缓存读取（读锁）
            cacheLock.readLock().lock();
            FileCacheEntry entry = jsonFileCache.get(filePath);
            cacheLock.readLock().unlock();

            // 缓存命中、未过期且文件未修改
            if (entry != null && !entry.isExpired() && entry.fileLastModified == fileLastModified) {
                return entry.node;
            }

            // 缓存未命中/过期/文件已修改，重新解析
            JsonNode rootNode = objectMapper.readTree(jsonFile);

            // 更新缓存（写锁）
            cacheLock.writeLock().lock();
            jsonFileCache.put(filePath, new FileCacheEntry(rootNode, fileLastModified));
            cacheLock.writeLock().unlock();

            return rootNode;
        } catch (Exception e) {
            log.error("JSON文件解析失败，路径=[{}]，错误=[{}]", filePath, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从根节点根据路径导航到目标节点（支持嵌套和数组索引）
     * 路径格式示例：
     * - 嵌套对象："user.info.name"
     * - 数组元素："list[0].id"
     * - 混合："data.users[2].address.city"
     *
     * @param rootNode 根节点
     * @param nodePath 节点路径
     * @return 目标节点；路径无效或节点不存在时返回null
     */
    private static JsonNode getNodeFromPath(JsonNode rootNode, String nodePath) {
        if (rootNode == null) {
            log.error("导航节点失败：根节点为空");
            return null;
        }
        if (nodePath == null || nodePath.trim().isEmpty()) {
            log.error("导航节点失败：节点路径为空");
            return null;
        }

        JsonNode currentNode = rootNode;
        // 按点分割路径片段（处理嵌套）
        String[] pathSegments = nodePath.split("\\.");

        // 遍历每个路径片段，导航到目标节点
        for (String segment : pathSegments) {
            // 处理数组索引（如"list[0]"中的[0]）
            int indexStart = segment.indexOf('[');
            int indexEnd = segment.indexOf(']');
            String nodeName = segment; // 节点名称（不含数组索引）
            Integer arrayIndex = null; // 数组索引（如为数组节点）

            // 解析数组索引
            if (indexStart != -1 && indexEnd != -1 && indexEnd > indexStart) {
                // 提取节点名称（如"list[0]"中的"list"）
                nodeName = segment.substring(0, indexStart);
                // 提取数组索引（如"list[0]"中的0）
                try {
                    arrayIndex = Integer.parseInt(segment.substring(indexStart + 1, indexEnd));
                } catch (NumberFormatException e) {
                    log.error("数组索引格式错误：片段=[{}]，错误=[{}]", segment, e.getMessage());
                    return null;
                }
            }

            // 导航到当前片段的节点
            currentNode = currentNode.get(nodeName);
            if (currentNode == null) {
                log.warn("节点[{}]不存在于路径中", nodeName);
                return null;
            }

            // 处理数组索引（如果有）
            if (arrayIndex != null) {
                if (!currentNode.isArray()) {
                    log.error("节点[{}]不是数组，无法获取索引[{}]", nodeName, arrayIndex);
                    return null;
                }
                if (arrayIndex < 0 || arrayIndex >= currentNode.size()) {
                    log.error("数组索引越界：节点[{}]长度为[{}]，索引=[{}]",
                            nodeName, currentNode.size(), arrayIndex);
                    return null;
                }
                currentNode = currentNode.get(arrayIndex); // 定位到数组指定元素
            }
        }

        return currentNode;
    }

    /**
     * 查找数组中匹配条件的目标节点（抽取公共逻辑）
     *
     * @param arrayNode      数组节点
     * @param conditionField 条件字段名
     * @param conditionValue 条件字段值
     * @param targetField    目标字段名
     * @return 目标字段对应的JsonNode；未找到返回null
     */
    private static JsonNode findTargetNodeInArray(JsonNode arrayNode, String conditionField,
                                                  String conditionValue, String targetField) {
        // 遍历数组（传统for循环，不使用流式编程）
        for (int i = 0; i < arrayNode.size(); i++) {
            JsonNode element = arrayNode.get(i);
            if (element == null) {
                log.warn("数组第{}个元素为空，跳过", i);
                continue;
            }

            // 匹配条件字段
            JsonNode conditionNode = element.get(conditionField);
            if (conditionNode == null) {
                log.debug("数组第{}个元素缺少条件字段[{}]，跳过", i, conditionField);
                continue;
            }

            // 条件值匹配（转为字符串比较，兼容多类型）
            if (conditionValue.equals(conditionNode.asText())) {
                JsonNode targetNode = element.get(targetField);
                if (targetNode == null) {
                    log.warn("匹配对象缺少目标字段[{}]", targetField);
                    return null;
                }
                return targetNode; // 找到匹配节点，返回目标字段节点
            }
        }

        log.info("未找到条件[{}={}]的对象", conditionField, conditionValue);
        return null;
    }

    /**
     * 从JSON字符串中获取条件查询的目标节点（抽取公共逻辑）
     *
     * @param jsonStr        JSON字符串
     * @param arrayPath      数组路径
     * @param conditionField 条件字段
     * @param conditionValue 条件值
     * @param targetField    目标字段
     * @return 目标字段节点；未找到返回null
     */
    private static JsonNode getTargetNodeByCondition(String jsonStr, String arrayPath,
                                                     String conditionField, String conditionValue,
                                                     String targetField) {
        // 入参校验
        if (jsonStr == null || jsonStr.trim().isEmpty() || arrayPath == null || arrayPath.trim().isEmpty()
                || conditionField == null || conditionField.trim().isEmpty() || conditionValue == null
                || targetField == null || targetField.trim().isEmpty()) {
            log.error("条件查询参数存在空值，返回null");
            return null;
        }

        // 获取数组节点
        JsonNode arrayNode = getTargetNodeFromString(jsonStr, arrayPath);
        if (arrayNode == null || !arrayNode.isArray()) {
            log.error("数组路径[{}]无效或不是数组", arrayPath);
            return null;
        }

        // 查找匹配的目标节点
        return findTargetNodeInArray(arrayNode, conditionField, conditionValue, targetField);
    }

    /**
     * 判断JSON字符串中指定节点是否为有效节点（非null、非空对象/数组）
     * @param jsonStr JSON格式字符串
     * @param nodePath 节点路径（如"data"）
     * @return true-节点存在且有效（非null、非空对象/数组）；false-节点无效或不存在；解析失败返回null
     */
    public static Boolean isNodeValid(String jsonStr, String nodePath) {
        try {
            // 直接获取原始JsonNode（不转为字符串）
            JsonNode targetNode = getTargetNodeFromString(jsonStr, nodePath);
            if (targetNode == null || targetNode.isNull()) {
                return false; // 节点不存在或为null
            }
            // 判断节点是否为空对象（{}）或空数组（[]）
            if ((targetNode.isObject() && targetNode.isEmpty()) ||
                    (targetNode.isArray() && targetNode.isEmpty())) {
                return false;
            }
            return true; // 节点存在且有效
        } catch (Exception e) {
            log.error("判断节点[{}]有效性异常", nodePath, e);
            return null; // 解析失败
        }
    }
}